<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>EnhancedGrid Demo</title>

<link rel="stylesheet" type="text/css" href="theme-local.css" />
<style type="text/css">
body {
    font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
    font-size: 11px;
}

#debugPanel pre {
    font-family: "Lucida Console", "Courier New", Courier, monospace;
}

div.container {
    border: 0px solid green;
    margin: 10px;
}
</style>

<script type="text/javascript">
var djConfig = {
    isDebug: true,
    parseOnLoad: true,
    locale: "zh",
    extraLocale: ["en"],
    baseUrl: "./lib/dojotoolkit/dojo/",
    modulePaths: {
        "demo": "../../../script/demo",
        "com": "../../../script/com"
    }
};
</script>
<script type="text/javascript" src="./lib/dojotoolkit/dojo/dojo.js"></script>
<script type="text/javascript">
    dojo.require("dojo.data.ItemFileWriteStore");
    dojo.require("dojo.date.locale");
    dojo.require("dojo.parser");

    dojo.require("dijit.dijit"); // optimize: load dijit layer
    dojo.require("dijit.ColorPalette");
    dojo.require("dijit.Dialog");
    dojo.require("dijit.form.CheckBox");
    dojo.require("dijit.form.ComboBox");
    dojo.require("dijit.form.Button");
    dojo.require("dijit.form.DateTextBox");
    dojo.require("dijit.form.DropDownButton");
    dojo.require("dijit.form.FilteringSelect");
    dojo.require("dijit.form.NumberSpinner");
    dojo.require("dijit.form.NumberTextBox");
    dojo.require("dijit.form.RadioButton");
    dojo.require("dijit.form.SimpleTextarea");
    dojo.require("dijit.form.Textarea");
    dojo.require("dijit.form.TextBox");
    dojo.require("dijit.form.ValidationTextBox");
    dojo.require("dijit.InlineEditBox");
    dojo.require("dijit.Menu");
    dojo.require("dijit.TitlePane");
    dojo.require("dijit.TooltipDialog");

    dojo.require("dojox.data.AndOrWriteStore");
    dojo.require("dojox.html.entities");
    dojo.require("dojox.layout.FloatingPane");
    dojo.require("dojox.layout.ResizeHandle");
    dojo.require("dojox.widget.Standby");
</script>
<script type="text/javascript" src="./script/utils.js"></script>
<script type="text/javascript" src="./script/grid.js"></script>
<script type="text/javascript">
function debug(messages) {
    var msg = demo.utils._getDebugMsg.apply(null, arguments);
    console.debug(msg);

    var msgDiv = dojo.byId("debugPanelContent");
    msgDiv.innerHTML = msg;
}

function append(messages) {
    var msg = demo.utils._getDebugMsg.apply(null, arguments);

    var msgDiv = dojo.byId("debugPanelContent");
    msgDiv.innerHTML += "\n" + msg;
}

function show(id) {
    demo.utils.show(id);
}

function hide(id) {
    demo.utils.hide(id);
}
</script>
<style type="text/css">
@import "./css/rounded-button.css";
@import "./css/rounded-corners.css";

body {
    padding: 10px;
}

.gridContainer {
    width: 100%;
    height: 300px;
}

/* Column selector pane */
.column-selector-pane {
    vertical-align: top;
}

.column-selector-pane li {
    list-style: none;
}

.smd-cell-pass {

}

.smd-cell-fail {
    text-align: center;
    background-color: red;
    color: white;
    font-weight: bold;
    font-size: 12pt;
}

.smd-cell-fail a {
    text-decoration: none;
    color: white;
}

.smd-cell-notapplicable {
    text-align: center;
    background-color: #eeeeee;
    color: #aaaaaa;
}

.smd-cell-notapplicable a {
    text-decoration: none;
    color: #aaaaaa;
    cursor: default;
}

a:hover {
    color: #6699cc;
}
</style>
<script type="text/javascript">
demo.grid.pageParameters = demo.utils.getPageParametersAsQueryString();
/**
 * checkboxes for select columns in grid
 */
demo.grid.checkboxes = [];

/**
 * Initial columns
 */
demo.grid.initialColumns = [];

demo.grid.cellCssClass = {
    PASS: "smd-cell-pass",
    FAIL: "smd-cell-fail",
    NOT_APPLICABLE: "smd-cell-notapplicable"
};

demo.grid.cellDisplayValue = {
    PASS: "",
    FAIL: "x",
    NOT_APPLICABLE: "n/a"
};

/**
 * Used to style Criterion field in ICAR grid.
 */
demo.grid.formatIcarCriterion = function(value, rowIndex) {
    var store = this.grid.store;
    var item = this.grid.getItem(rowIndex);
    if (item) {
        var driverColour = store.getValue(item, "consumability-market-driver-color");
        if (driverColour)
            this.customStyles.push("background:" + driverColour + "; ");
    }

    return value;
};

/**
 * Used to style flags in ICAR grid.
 */
demo.grid.formatIcarFlag = function(value, rowIndex) {
    var displayValue = value;

    if (value === null || value === undefined) {
        this.customClasses.push(demo.grid.cellCssClass.NOT_APPLICABLE);
        displayValue = demo.grid.cellDisplayValue.NOT_APPLICABLE;
    } else {
        var intValue = demo.utils.toInt(value);
        switch (intValue) {
            case -1:
                this.customClasses.push(demo.grid.cellCssClass.NOT_APPLICABLE);
                displayValue = demo.grid.cellDisplayValue.NOT_APPLICABLE;
                break;
            case 0:
                this.customClasses.push(demo.grid.cellCssClass.PASS);
                displayValue = demo.grid.cellDisplayValue.PASS;
                break;
            case 1:
                this.customClasses.push(demo.grid.cellCssClass.FAIL);
                displayValue = demo.grid.cellDisplayValue.FAIL;
        }
    }

    // Build link
    var link = "";

    switch (this.name) {
        case "Client Survey Priority":
            url = demo.utils.format("./drill_csp/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                help: "Drill down to assessmemt results criterion view"
            });
            break;
        case "Client Survey <= 2.0":
            url = demo.utils.format("./drill_csp/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                help: "Drill down to survey results criterion view"
            });
            break;
        case "Self Assessment <= 2.0":
            url = demo.utils.format("./drill_isa/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                help: "Drill down to assessmemt results criterion view"
            });
            break;
        case "Lab Services <= 2.0":
            url = demo.utils.format("./drill_Lsa/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                help: "Drill down to survey results criterion view"
            });
            break;
        case "Top 5 OPC PMR Data": // NOTE: useless
            url = demo.utils.format("./drill_tpc/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                help: "Drill down to PMRs impacting consumability"
            });
            break;
        case "Stack Interoperability Priority": // NOTE: useless
            url = demo.utils.format("./drill_stack/{0}", demo.grid.pageParameters);
            link = demo.utils.buildLink({
                text: displayValue,
                url: url,
                onclick: "showGridColumnsDialog(); return false;"
            });
            break;
        default:
            link = displayValue;
    }

    var html = "";
    html = link;
    return html;
};

/**
 * Used to style top 5 in ICAR grid
 */
demo.grid.formatIcarTop5 = function(value, rowIndex) {
    var displayValue = value;

    if (value === null || value === undefined) {
        this.customClasses.push(demo.grid.cellCssClass.NOT_APPLICABLE);
        displayValue = demo.grid.cellDisplayValue.NOT_APPLICABLE;
    } else {
        var intValue = demo.utils.toInt(value);

        if (intValue >= 1 && intValue <= 5) {
            this.customClasses.push(demo.grid.cellCssClass.FAIL);
            displayValue = demo.grid.cellDisplayValue.FAIL;
        } else
            if (intValue > 5) {
                this.customClasses.push(demo.grid.cellCssClass.PASS);
                displayValue = demo.grid.cellDisplayValue.PASS;
            } else {
                this.customClasses.push(demo.grid.cellCssClass.NOT_APPLICABLE);
                displayValue = demo.grid.cellDisplayValue.NOT_APPLICABLE;
            }
    }

    // Build link
    var url = demo.utils.format("./drill_tpc/{0}", demo.grid.pageParameters);
    var link = demo.utils.buildLink({
        text: displayValue,
        url: url,
        help: "Drill down to PMRs impacting consumability"
    });

    var html = "";
    html = link;

    return html;
};

/**
 * Used to style Stack Interoperability Priority field in ICAR grid.
 */
demo.grid.formatIcarInterop = function(value, rowIndex) {
    var displayValue = value;

    if (value === null || value === undefined) {
        this.customClasses.push(demo.grid.cellCssClass.NOT_APPLICABLE);
        displayValue = demo.grid.cellDisplayValue.NOT_APPLICABLE;
    } else {
        var intValue = demo.utils.toInt(value);
        switch (intValue) {
            case 0:
                this.customClasses.push(demo.grid.cellCssClass.PASS);
                displayValue = demo.grid.cellDisplayValue.PASS;
                break;
            default:
                this.customClasses.push(demo.grid.cellCssClass.FAIL);
                displayValue = demo.grid.cellDisplayValue.FAIL;
        }
    }

    if (displayValue === demo.grid.cellDisplayValue.NOT_APPLICABLE) {
        return displayValue;
    }

    // Build link
    var item = this.grid.getItem(rowIndex);
    var store = this.grid.store;

    var criterionToken = store.getValue(item, "consumability-criterion-token");
    var criterion = store.getValue(item, "consumability-criterion");
    var consAttrMappedValue = demo.grid.getConsAttrMappedValue(criterion);

    var url = demo.utils.format("./drill_stack/{0}/{1}/{2}/{3}", value || "", criterionToken, consAttrMappedValue, demo.grid.pageParameters);
    var onclick = "demo.grid.showStackDrillDialog(this); return false;";
    var link = demo.utils.buildLink({
        text: displayValue,
        url: url,
        onclick: onclick
    });

    var html = "";
    html = link;

    return html;
};

demo.grid.cons_attr_Mapping = null;

demo.grid.buildConsAttrMapping = function() {
    var mapping = {};
    var mappedValue = null;

    var _addMapping = function(key, value) {
        mapping[key] = value;
    };

    // Attribute Acquire
    mappedValue = "ER6Acquire_d";
    _addMapping("Package complete", mappedValue);

    // Attribute Install
    mappedValue = "ER6InstallmB";
    _addMapping("Evaluation setup", mappedValue);
    _addMapping("Ease of installation", mappedValue);
    _addMapping("Verified installation dependencies", mappedValue);
    _addMapping("Install - other", mappedValue);

    // Attribute Configure
    mappedValue = "ER8Configure8a";
    _addMapping("Changing my configuration", mappedValue);

    // Attribute Operate
    mappedValue = "ER6Operatefx";
    _addMapping("Skill and role appropriate tools and information", mappedValue);
    _addMapping("Access to operational information", mappedValue);
    _addMapping("Operate - other", mappedValue);

    // Attribute Integrate
    mappedValue = "ER8Integrate9X";
    _addMapping("Interfaces to services or facilities", mappedValue);
    _addMapping("Nondisruptive operation", mappedValue);
    _addMapping("Interoperability with related products", mappedValue);
    _addMapping("Integrated cross-product user experience", mappedValue);
    _addMapping("Integrate - other", mappedValue);

    // Attribute Deploy
    mappedValue = "ER5Deploy1C";
    _addMapping("Simplified deployment into production", mappedValue);

    // Attribute Develop
    mappedValue = "ER6Developel";
    _addMapping("Materials to start application development immediately", mappedValue);
    _addMapping("Easy-to-use development environment", mappedValue);
    _addMapping("User interface ease of use", mappedValue);
    _addMapping("Develop - other", mappedValue);

    // Attribute Problem Management
    mappedValue = "ERHProblem_ManagementFw";
    _addMapping("Support response", mappedValue);
    _addMapping("Problem determination and troubleshooting capabilities", mappedValue);
    _addMapping("Problem Management - other", mappedValue);

    // Attribute Administer / Maintain
    mappedValue = "ERKAdminister_$_Maintain$$jUZ";
    _addMapping("Consistent administrative tools", mappedValue);

    // Attribute Fix / Update
    mappedValue = "ERBFix_$_Update$$jmk";
    _addMapping("Verified update dependencies", mappedValue);
    _addMapping("Nondisruptive fix packs", mappedValue);
    _addMapping("Real-time fix identification and delivery", mappedValue);
    _addMapping("Ease of upgrade", mappedValue);
    _addMapping("Update interoperability with related products", mappedValue);
    _addMapping("Fix / Update - other", mappedValue);

    demo.grid.cons_attr_Mapping = mapping;
};

demo.grid.getConsAttrMappedValue = function(criterion) {
    var mapping = demo.grid.cons_attr_Mapping;
    if (!mapping) {
        demo.grid.buildConsAttrMapping();
        mapping = demo.grid.cons_attr_Mapping;
    }

    if (criterion in mapping) {
        return mapping[criterion];
    } else {
        return criterion;
    }
};

demo.grid._getConsAttrMappedValue = function(criterion) {
    var mappedValue = null;

    switch (criterion) {
        // Attribute Acquire
        case "Package complete":
            mappedValue = "ER6Acquire_d";
            break;
        // Attribute Install
        case "Evaluation setup":
        case "Ease of installation":
        case "Verified installation dependencies":
        case "Install - other":
            mappedValue = "ER6InstallmB";
            break;
        // Attribute Configure
        case "Changing my configuration":
            mappedValue = "ER8Configure8a";
            break;
        // Attribute Operate
        case "Skill and role appropriate tools and information":
        case "Access to operational information":
        case "Operate - other":
            mappedValue = "ER6Operatefx";
            break;
        // Attribute Integrate
        case "Interfaces to services or facilities":
        case "Nondisruptive operation":
        case "Interoperability with related products":
        case "Integrated cross-product user experience":
        case "Integrate - other":
            mappedValue = "ER8Integrate9X";
            break;
        // Attribute Deploy
        case "Simplified deployment into production":
            mappedValue = "ER5Deploy1C";
            break;
        // Attribute Develop
        case "Materials to start application development immediately":
        case "Easy-to-use development environment":
        case "User interface ease of use":
        case "Develop - other":
            mappedValue = "ER6Developel";
            break;
        // Attribute Problem Management
        case "Support response":
        case "Problem determination and troubleshooting capabilities":
        case "Problem Management - other":
            mappedValue = "ERHProblem_ManagementFw";
            break;
        // Attribute Administer / Maintain
        case "Consistent administrative tools":
            mappedValue = "ERKAdminister_$_Maintain$$jUZ";
            break;
        // Attribute Fix / Update
        case "Verified update dependencies":
        case "Nondisruptive fix packs":
        case "Real-time fix identification and delivery":
        case "Ease of upgrade":
        case "Update interoperability with related products":
        case "Fix / Update - other":
            mappedValue = "ERBFix_$_Update$$jmk";
            break;
        default:
            mappedValue = criterion;
    }

    return mappedValue;
};

//////////////////////////////
demo.grid.getGridStructure = function(grid) {
    var struct_views = [];

    dojo.forEach(grid.layout.structure, function(viewStructure) {
        if (viewStructure.type === "dojox.grid._RowSelector") {
            struct_views.push("rowSelector");
            return;
        }

        var cells = viewStructure.cells[0];
        var struct_cells = dojo.map(cells, function(cell) {
            return cell.id;
        });
        struct_views.push(struct_cells);
    });

    console.info("views", struct_views);
    return struct_views;
};

///////////////////////////////////////////////////////
demo.grid.makeGridStore = function(data) {
    // Store for grid
    var storeData = {
        identifier: "consumability-criterion",
        label: "consumability-criterion",
        items: data.rowset
    };

    var store = new dojo.data.ItemFileWriteStore({
        data: storeData
    });

    return store;
};

demo.grid.makeGridLayout = function(data) {
    var layout = null;

    var columnDefs = data.metadata.columns;

    var columnTitles = [];
    columnTitles.push("Criterion");
    columnTitles.push("Client Survey Priority");
    columnTitles.push("Client Survey <= 2.0");
    columnTitles.push("Self Assessment <= 2.0");
    columnTitles.push("Lab Services <= 2.0");
    columnTitles.push("Top 5 OPC PMR Data");
    columnTitles.push("Stack Interoperability Priority");
    columnTitles.push("Brand Defined Indicator");

    var columns = dojo.map(columnTitles, function(columnTitle) {
        var matchedColumnDefs = dojo.filter(columnDefs, function(columnDef) {
            return (columnDef.title === columnTitle);
        });

        var columnDef = null;
        if (matchedColumnDefs.length > 0)
            columnDef = matchedColumnDefs[0];

        var column = {};
        column.name = columnDef.title;
        column.field = columnDef.name;
        column.attrs = 'title="' + columnDef.title + '"';

        // width
        if (column.name === "Criterion") {
            column.width = "200px";
        } else {
            column.relWidth = 1; // relative width
        }

        // formatter
        var formatter = null;
        switch (column.name) {
            case "Criterion":
                formatter = demo.grid.formatIcarCriterion;
                break;
            case "Top 5 OPC PMR Data":
                formatter = demo.grid.formatIcarTop5;
                break;
            case "Stack Interoperability Priority":
                formatter = demo.grid.formatIcarInterop;
                break;
            default:
                formatter = demo.grid.formatIcarFlag;
        }

        column.formatter = formatter;

        return column;
    });

    layout = columns;
    return layout;
};

demo.grid.makeGrid = function(nodeId, data) {
    console.time("grid");
    // initialize tree grid
    var grid = dijit.byId("grid");

    if (!grid) {
        dojo.byId("title").innerHTML = data.metadata.title;
        demo.grid.formatMetadata(dojo.byId("metadata"), data.metadata.description);
        dojo.byId("footer").innerHTML = data.metadata.footer || "xxx Confidential";

        // Store for grid
        var store = demo.grid.makeGridStore(data);

        // Structure for grid
        var layout = demo.grid.makeGridLayout(data);

        var configuration = {
            node: nodeId
        };

        var params = {
            id: nodeId,
            store: store,
            structure: layout,
            width: "100%",
            autoWidth: false,
            autoHeight: true,
            columnReordering: true
        };
        configuration.params = params;

        var plugins = {
            indirectSelection: false,
            nestedSorting: true,
            dnd: true,
            menus: {
                headerMenu: "headerMenu"
                //rowMenu: "rowMenu",
                //cellMenu: "cellMenu",
                //selectedRegionMenu: "selectedRegionMenu"
            }
        };
        configuration.plugins = plugins;

        var eventHandlers = {
            // fix onCellClick to avoid to focus cell when click on cell content
            //"onCellClick": demo.grid.onCellClick
        };
        configuration.eventHandlers = eventHandlers;

        grid = demo.grid.buildGrid(configuration);

        // button for select columns to display
        var button = new dijit.form.Button({
            id: "columnSelectorButton",
            label: "Select columns to display",
            onClick: showColumnSelectorDialog
        });
        dojo.byId("gridToolbarContainer").appendChild(button.domNode);
    }
    console.timeEnd("grid");
};

//////////////////////////////
demo.grid.getStackDrillDialog = function() {
    var dialog = dijit.byId("stackDrillDialog");

    if (!dialog) {
        var pane = dojo.create("div");

        // create close button for popup
        dojo.place('<a class="closett" href="javascript://" onclick="demo.grid.hideStackDrillDialog();return false;"><img src="./images/icons/close.png" alt="close" title="close" align="right" /></a>', pane);

        // create the table place holder and add it to the popup dialog
        var tableNode = dojo.place('<table><tbody></tbody></table>', pane);

        // create dialog
        var dialog = new dijit.TooltipDialog({
            id: "stackDrillDialog",
            title: "Affected stacks",
            onBlur: function() {
                dijit.popup.close(this);
            },
            onCancel: function() {
                dijit.popup.close(this);
            }
        }, pane);
        dialog.startup();
    }

    return dialog;
};

demo.grid.hideStackDrillDialog = function(e) {
    var dialog = dijit.byId("stackDrillDialog");
    if (dialog) {
        dijit.popup.close(dialog);
    }
};

demo.grid.showStackDrillDialog = function(linkNode) {
    // get list of stack groups from link href
    // "drill_stack/{stacks}/{criterionToken}/{criterionAttr}/{analysisSpecifier}"
    var parts = linkNode.href.split("/");
    parts.reverse();
    var stacks = parts[3];

    if (!stacks || stacks === "null") {
        return;
    }

    // fill dialog content
    var dialog = demo.grid.getStackDrillDialog();
    var contentNode = dojo.query("table tbody", dialog.containerNode)[0];
    dojo.empty(contentNode);

    var stackGroups = decodeURI(stacks).split(" ");
    dojo.forEach(stackGroups, function(stackGroupMoniker) {
        var stackGroupUrl = linkNode.href.replace(stacks, stackGroupMoniker);
        var rowNode = dojo.create("tr", null, contentNode);
        demo.grid.getStackDetails(stackGroupMoniker, stackGroupUrl, rowNode);
    });

    // show drilldown dialog
    dijit.popup.open({
        popup: dialog,
        around: linkNode
    });
};

demo.grid.getStackDetails = function(moniker, stackGroupUrl, rowNode) {
    // URL to obtain product group or product details, requesting response in JSON format.
    var url = "http://9.123.233.103:9080/dashboard" + "/admin/productgroups/" + moniker + "?output=json";

    dojo.xhrGet({
        url: "./data/product-group.json",
        handleAs: "json",
        sync: true,
        // A successful response will contain details for a single product group. Use this to iniialise the popup dialog.
        load: function(productGroup, ioargs) {
            // add a cell to the table with stack product group name and hyperlink for drilldown
            var pgName = productGroup.name;
            var nameCellNode = dojo.create("td", {
                noWrap: true
            }, rowNode);
            var link = dojo.create("a", {
                href: stackGroupUrl,
                innerHTML: pgName
            }, nameCellNode);

            // add a cell to the table with stack product group description
            var pgDescription = productGroup.description;
            var descriptionCellNode = dojo.create("td", {
                innerHTML: pgDescription
            }, rowNode);
        },
        // Recognised errors are reported explicitly. Unexpected errors are reported generically.
        error: function(response, ioargs) {
            console.error("ajax");
        }
    });
};

//////////////////////////////
dojo.addOnLoad(function() {
    debug("loading");

    var url = "./data/grid/icar.json";
    dojo.xhrGet({
        url: url,
        handleAs: "json",
        load: function(response, ioargs) {
            debug("loaded");
            demo.grid.makeGrid("grid", response);
        }
    });
});

//////////////////////////////
// showColumnSelectorDialogButton
function showColumnSelectorDialog() {
    var grid = dijit.byId("grid");
    demo.grid.buildColumnSelectorContainer(grid, "columnSelectorContainer", 5);
    dijit.byId("gridColumnsDialog").show();
}

// showColumnsButton
function showColumns() {
    var grid = dijit.byId("grid");
    demo.grid.showSelectedColumns(grid);
    dijit.byId("gridColumnsDialog").hide();
}

// cancelSelectColumnsButton
function cancelSelectColumns() {
    dijit.byId("gridColumnsDialog").hide();
}

function restoreColumns() {
    var grid = dijit.byId("grid");
    demo.grid.restoreColumns(grid);
}
</script>
</head>
<body class="tundra">

  <div id="main" class="container">

    <div id="titlePanel" dojoType="dijit.TitlePane" title="Panel" style="">
      <div id="resizablePanel" style="position:relative; padding: 10px; border:1px solid black;">

        <!-- Content -->
        <div class="content">
            <div id="title" style="font-weight: bold;"></div>
            <!-- grid toolbar -->
            <div id="gridToolbarContainer"></div>
            <!-- grid -->
            <div id="grid"></div>
            <div id="metadata"></div>
            <div id="footer" style="text-align: center; font-weight: bold; font-size: smaller; color: #880000;"></div>
        </div>

        <!-- Resize Handle -->
        <div id="resizeHandle" dojoType="dojox.layout.ResizeHandle" targetId="resizablePanel"></div>
      </div>
    </div>

    <!-- Button Panel -->
    <div dojoType="dojo.dnd.Moveable">
      <div id="buttonPanel" dojoType="dijit.TitlePane" title="Button Panel" style="">
        <!-- Show "Select columns to display" dialog -->
        <button dojoType="dijit.form.Button" onClick="showColumnSelectorDialog();">Show columns dialog</button>

        <!-- Drop Down Button -->
        <button dojoType="dijit.form.DropDownButton" iconClass="noteIcon" title="Select columns" value="Select columns" menu="">
          <span>Select columns</span>
          <!-- Header Menu -->
          <div dojoType="dijit.Menu" id="headerMenu" style="display: none;">
            <div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns"></div>
          </div>
        </button>

        <!-- Restore columns -->
        <button dojoType="dijit.form.Button" onClick="restoreColumns();">Restore columns</button>
      </div>
    </div>
  </div>

  <!-- Debug Panel -->
  <div id="debugPanel" dojoType="dojox.layout.FloatingPane" title="Console" resizable="true" dockable="true" style="position: absolute; bottom: 20px; right: 20px; width: 500px; height: 150px;">
    <pre id="debugPanelContent"></pre>
  </div>

  <!-- Show Columns Dialog -->
  <div dojoType="dijit.Dialog" id="gridColumnsDialog" title="Select Columns" style="display: none;">
    <div id="columnSelectorContainer"></div>
    <div style="clear: both;" class="hrule-dots">&nbsp;</div>
    <div id="showColumnsButton" dojoType="dijit.form.Button" onClick="showColumns();">Show columns</div>
    <div id="cancelSelectColumnsButton" dojoType="dijit.form.Button" onClick="cancelSelectColumns();">Cancel</div>
  </div>
</body>
</html>
